package com.eestimate.services;

import java.util.List;

import com.eestimate.dao.DAO;
import com.eestimate.domain.Company;
import com.eestimate.domain.Employee;
import com.eestimate.domain.business.BusinessObject;
import com.eestimate.domain.business.common.BusinessObjectTypeEnum;
import com.eestimate.domain.business.common.RelationshipTypeEnum;
import com.eestimate.exceptions.ErrorCodeEnum;
import com.eestimate.exceptions.ServiceException;
import com.eestimate.utils.Constants;
import com.eestimate.utils.EmailTemplateEnum;
import com.eestimate.utils.EmailUtils;
import com.eestimate.utils.EncryptionUtils;
import com.eestimate.utils.PropertiesUtils;
import com.eestimate.utils.ServiceUtils;
import com.eestimate.valuesobjects.CompanyVo;
import com.eestimate.valuesobjects.EmployeeVo;

public class EmployeeService {
	
	private DAO dao;
	
	public EmployeeVo fetchEmployee(String email,String password) throws ServiceException{
		try{
			Employee employee =  (Employee)dao.findBusinessObjectByMetadata(BusinessObjectTypeEnum.EMPLOYEE, "email", email);
			
			if(employee == null)
				throw new ServiceException("Employee not found by email:"+email,ErrorCodeEnum.EMPLOYEE_NOT_FOUND);
			
			if(EncryptionUtils.checkPassword(password, employee.getPassword())){
				return (EmployeeVo)employee.createDTO();
			}
			else{
				throw new ServiceException("Invalid Credentials",ErrorCodeEnum.INVALID_CREDENTIALS);
			}
		}
		catch(ServiceException exc){
			throw exc;
		}
		catch(Exception exc){
			throw new ServiceException(exc.getMessage(),exc,ErrorCodeEnum.INTERNAL_SERVER_ERROR);
		}		
	}
	
	public EmployeeVo login(String email, String password) throws ServiceException{
		try{
			ServiceUtils.verifyNotBlank(email, "Email");
			ServiceUtils.verifyNotBlank(password, "Password");
			
			List<String> employeeUuids = dao.findUuidsByMetadata(BusinessObjectTypeEnum.EMPLOYEE, "email", email);
			if(employeeUuids == null || employeeUuids.size() < 1) {
				throw new ServiceException("Employee with email:"+email+" not found.",ErrorCodeEnum.EMPLOYEE_NOT_FOUND);
			}
			
			Employee employee = (Employee) dao.getBusinessObjectByUuid(employeeUuids.get(0));
			
			if(!EncryptionUtils.checkPassword(password, employee.getPassword())){
				throw new ServiceException("Invalid credentials.", ErrorCodeEnum.INVALID_CREDENTIALS);
			}
				
			
			EmployeeVo employeeVo = (EmployeeVo)employee.createDTO();
			
			Company company = (Company)dao.getBusinessObjectByUuid(employee.getCompanyUuid());
			if(company!=null){
				CompanyVo companyVo = (CompanyVo)company.createDTO();
				employeeVo.company = companyVo;
			}
			
			return employeeVo;
		}
		catch(ServiceException exc){
			throw exc;
		}
		catch(Exception exc){
			throw new ServiceException(exc.getMessage(), exc, ErrorCodeEnum.INTERNAL_SERVER_ERROR);
		}
	}
	
	public EmployeeVo createEmployee(EmployeeVo employeeVo) throws ServiceException{
		
		try{
			ServiceUtils.verifyNotBlank(employeeVo.firstName, "FirstName");
			ServiceUtils.verifyNotBlank(employeeVo.email, "Email");
			ServiceUtils.verifyNotBlank(employeeVo.password, "Password");
			ServiceUtils.verifyNotBlank(employeeVo.company.name, "CompanyName");
			
			//check if a employee with this email already exists
			List<String> employeeUuids = dao.findUuidsByMetadata(BusinessObjectTypeEnum.EMPLOYEE, "email", employeeVo.email);
			
			//if a employee with this email already exists, then dont create a new one
			if(employeeUuids.size() > 0) {
				throw new ServiceException("Employee email:"+employeeVo.email+" already exists.",ErrorCodeEnum.EMAIL_ALREADY_EXISTS);
			}
			
			//Check if company already exists.
			List<BusinessObject> companiesList = dao.getBusinessObjectByName(BusinessObjectTypeEnum.COMPANY, employeeVo.company.name);
			
			Company company = null;
			
			//True: Company Exists
			//False: Company not exists. Create New
			if(companiesList!=null && companiesList.size()>0){
				company = (Company)companiesList.get(0);
				//TODO: Check also the company type
			}
			else{
				company 				= (Company)dao.emptyBusinessObject(BusinessObjectTypeEnum.COMPANY, employeeVo.company.name, Constants.SYSTEM_USER);
				company.setAddress(employeeVo.company.address);
				company.setOverview(employeeVo.company.overview);
				company.setCompanyType(employeeVo.company.companyType);
				company.setWebLink(employeeVo.company.webLink);
				company.setLicenseNumber(employeeVo.company.licenseNumber);
				company.setLicenseLink(employeeVo.company.licenseLink);
				company.setCountry(employeeVo.company.country);
				
				//Saving new company
				company		= (Company)dao.saveBusinessObject(company);
				
			}
			
			Employee employee = (Employee)dao.emptyBusinessObject(BusinessObjectTypeEnum.EMPLOYEE, employeeVo.firstName+" "+employeeVo.lastName, Constants.SYSTEM_USER);
			employee.setFirstName(employeeVo.firstName);
			employee.setLastName(employeeVo.lastName);
			employee.setEmail(employeeVo.email);
			employee.setPassword(EncryptionUtils.encryptPassword( employeeVo.password ));
			employee.setPhone(employeeVo.phone);
			employee.setCompanyUuid(company.getUuid());
			//Saving Employee
			employee = (Employee)dao.saveBusinessObject(employee);
			
			//Now make relationship
			dao.saveRelationship(company.getUuid(), employee.getUuid(), RelationshipTypeEnum.COMPANY_EMPLOYEE.getRelationshipName(), Constants.SYSTEM_USER);
			
			CompanyVo companyVo = (CompanyVo)company.createDTO();
			
			employeeVo = (EmployeeVo)employee.createDTO();
			
			employeeVo.company = companyVo;
			
			return employeeVo;
		}	
		catch(ServiceException exc){
			throw exc;
		}
		catch(Exception exc){
			throw new ServiceException(exc.getMessage(), exc, ErrorCodeEnum.INTERNAL_SERVER_ERROR);
		}
	}
	
	public void deleteEmployeeByUuid(String uuid) throws ServiceException{
		try{
			dao.deleteBusinessObjectByUuid(uuid);}
		catch(ServiceException exc){
			throw exc;
		}
		catch (Exception e) {
			throw new ServiceException(e.getMessage(), e, ErrorCodeEnum.INTERNAL_SERVER_ERROR);
		}
	}
	
	public EmployeeVo registerAndSendEmail(EmployeeVo employeeVo)throws ServiceException {
		EmployeeVo vo = createEmployee(employeeVo);
		
		//Send Email
		boolean sendEmail = Boolean.parseBoolean(PropertiesUtils.getInstance().getProperty(Constants.KEY_REGISTRATION_ALERT));
		if(sendEmail){
			EmailUtils.sendEmail(employeeVo.firstName+" "+employeeVo.lastName, employeeVo.email, employeeVo.password, EmailTemplateEnum.NEW_REGISTRATION);	
		}
		
		return vo;
	}
	

	public void setDao(DAO dao) {
		this.dao = dao;
	}
		
}
